package com.jming.jike.service.backend.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jming.jike.common.BusinessException;
import com.jming.jike.common.PageResult;
import com.jming.jike.dto.backend.DishDTO;
import com.jming.jike.entity.Category;
import com.jming.jike.entity.Dish;
import com.jming.jike.entity.DishFlavor;
import com.jming.jike.entity.SetMealDish;
import com.jming.jike.enums.StatusEnum;
import com.jming.jike.mapper.CategoryMapper;
import com.jming.jike.mapper.DishMapper;
import com.jming.jike.mapper.SetMealDishMapper;
import com.jming.jike.service.backend.DishFlavorService;
import com.jming.jike.service.backend.DishService;
import com.jming.jike.util.CommonUtils;
import com.jming.jike.util.CopyBeanUtils;
import com.jming.jike.vo.backend.CategoryVO;
import com.jming.jike.vo.backend.DishDetailVO;
import com.jming.jike.vo.backend.DishFlavorVO;
import com.jming.jike.vo.backend.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static com.jming.jike.enums.StatusEnum.START_STATUS;
import static com.jming.jike.enums.StatusEnum.STOP_STATUS;

/**
 * 菜品管理(Dish)表服务实现类
 *
 * @author makejava
 * @since 2022-04-16 02:02:52
 */
@Slf4j
@Service
public class DishServiceImpl implements DishService {

    @Resource
    private DishMapper dishMapper;

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private DishFlavorService dishFlavorService;

    @Resource
    private SetMealDishMapper setMealDishMapper;

    @Resource
    private CommonUtils commonUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(DishDTO dishDTO) {

        // 菜品信息
        dishDTO.setId(null);
        Dish dish = CopyBeanUtils.copyBean(dishDTO, new Dish());

        log.info("DishServiceImpl insert 添加菜品信息 入参 {}", JSON.toJSONString(dish));
        // 添加菜品信息
        if (dishMapper.insert(dish) <= 0) {
            throw new BusinessException("添加菜品失败!");
        }

        // 添加口味信息
        List<DishFlavor> dishFlavorList = dishDTO.getDishFlavorDTOList().stream().map(df -> {
            DishFlavor dishFlavor = CopyBeanUtils.copyBean(df, new DishFlavor());
            dishFlavor.setId(null);
            dishFlavor.setDishId(dish.getId());
            return dishFlavor;
        }).collect(Collectors.toList());
        log.info("DishServiceImpl insert 批量添加口味信息 入参 {}", JSON.toJSONString(dishFlavorList));
        // 批量添加口味信息
        return dishFlavorService.saveBatch(dishFlavorList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(DishDTO dishDTO) {

        log.info("DishServiceImpl update 修改菜品信息 入参 {}", JSON.toJSONString(dishDTO));

        // 查询菜品信息 如果不存在则抛出异常
        Dish dish = dishMapper.selectById(dishDTO.getId());
        if (ObjectUtils.isEmpty(dish)) {
            throw new BusinessException("修改的菜品不存在!");
        }

        // 修改菜品信息
        if (dishMapper.updateById(CopyBeanUtils.copyBean(dishDTO, new Dish())) <= 0) {
            throw new BusinessException("修改失败!");
        }

        // 删除原来的口味信息
        if (!dishFlavorService.update(Wrappers.<DishFlavor>lambdaUpdate()
                .eq(DishFlavor::getDishId, dishDTO.getId())
                .set(DishFlavor::getIsDeleted, 1))) {
            throw new BusinessException("口味更新失败!");
        }

        // 添加口味信息
        List<DishFlavor> dishFlavorList = dishDTO.getDishFlavorDTOList().stream().map(df -> {
            DishFlavor dishFlavor = CopyBeanUtils.copyBean(df, new DishFlavor());
            dishFlavor.setId(null);
            dishFlavor.setDishId(dishDTO.getId());
            return dishFlavor;
        }).collect(Collectors.toList());
        log.info("DishServiceImpl update 修改口味信息 入参 {}", JSON.toJSONString(dishFlavorList));

        // 批量添加口味信息
        if (!dishFlavorService.saveBatch(dishFlavorList)) {
            throw new BusinessException("口味添加失败");
        }

        // 更新图片
        return commonUtils.removeImage(dish.getImage(), dishDTO.getImage());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long id) {

        // 检查菜品
        this.checkDish(id, "删除");

        // 查询该菜品信息
        Dish dish = dishMapper.selectById(id);

        if (ObjectUtils.isEmpty(dish)
                || Integer.valueOf(1).equals(dish.getIsDeleted())
                || START_STATUS.getCode().equals(dish.getStatus())) {

            throw new BusinessException("请检查菜品是否存在或状态是否为停售!");
        }

        // 删除菜品信息
        if (dishMapper.updateById(Dish.builder().id(id).isDeleted(1).build()) <= 0) {
            throw new BusinessException("删除失败!");
        }

        // 删除口味信息
        if (!dishFlavorService.update(Wrappers.<DishFlavor>lambdaUpdate()
                .eq(DishFlavor::getDishId, id)
                .set(DishFlavor::getIsDeleted, 1))) {
            throw new BusinessException("删除失败!");
        }

        // 删除图片
        return commonUtils.removeImage(dish.getImage(), null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(Long id, Integer status) {

        // 检查入参
        StatusEnum.checkStatus(status);

        // 如果修改为停售状态 检查菜品是否绑定了套餐
        if (STOP_STATUS.getCode().equals(status)) {
            this.checkDish(id, "停售");
        }

        // 修改菜品状态
        return dishMapper.updateById(Dish.builder().id(id).status(status).build()) > 0;
    }

    @Override
    public PageResult<DishVO> pageQuery(DishDTO dishDTO) {

        // 分页查询菜品信息
        Page<Dish> dishPage = dishMapper.selectPage(new Page<>(dishDTO.getPageIndex(), dishDTO.getPageSize()),
                Wrappers.<Dish>lambdaQuery().eq(Dish::getIsDeleted, 0)
                        .like(StringUtils.hasText(dishDTO.getName()), Dish::getName, dishDTO.getName())
                        .orderByAsc(Dish::getSort)
                        .orderByDesc(Dish::getId));

        if (ObjectUtils.isEmpty(dishPage) || CollectionUtils.isEmpty(dishPage.getRecords())) {
            throw new BusinessException("菜品列表为空!");
        }

        // 处理返回数据
        List<DishVO> dishVOList = dishPage.getRecords().stream().map(d -> {
            DishVO dishVO = CopyBeanUtils.copyBean(d, new DishVO());

            // 查询菜品分类信息 设置菜品分类名称
            Category category = categoryMapper.selectById(d.getCategoryId());
            dishVO.setCategoryName(category.getName());
            return dishVO;
        }).collect(Collectors.toList());

        // 返回分页信息
        return new PageResult<>((int) dishPage.getCurrent(), (int) dishPage.getSize(),
                (int) dishPage.getTotal(), dishVOList);
    }

    @Override
    public DishDetailVO queryDetail(Long id) {

        // 查询菜品信息
        DishVO dishVO = CopyBeanUtils.copyBean(dishMapper.selectById(id), new DishVO());

        // 查询分类信息
        CategoryVO categoryVO = CopyBeanUtils.copyBean(categoryMapper.selectById(dishVO.getCategoryId()), new CategoryVO());

        // 查询口味列表
        List<DishFlavorVO> dishFlavorVOList = CopyBeanUtils.copyBeanList(dishFlavorService.list(Wrappers.<DishFlavor>lambdaQuery()
                .eq(DishFlavor::getIsDeleted, 0)
                .eq(DishFlavor::getDishId, id)
                .orderByAsc(DishFlavor::getId)), DishFlavorVO.class);

        // 返回详菜品细信息
        return DishDetailVO.builder().dishVO(dishVO).categoryVO(categoryVO).dishFlavorVOList(dishFlavorVOList).build();
    }

    /**
     * 检查菜品是否绑定了套餐
     *
     * @param id
     * @param operDesc
     * @Author jinming.zhang
     * @Date 2022/4/24
     */
    private void checkDish(Long id, String operDesc) {

        // 查询该菜品是否绑定了套餐信息
        if (!ObjectUtils.isEmpty(setMealDishMapper.selectOne(Wrappers.<SetMealDish>lambdaQuery()
                .eq(SetMealDish::getIsDeleted, 0)
                .eq(SetMealDish::getDishId, id)
                .last("limit 1")))) {

            throw new BusinessException("该菜品绑定了套餐, 不可" + operDesc + "!");
        }

    }

}
